package com.voice.call.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.voice.call.common.Const;
import com.voice.call.common.ConstLang;
import com.voice.call.common.Result;
import com.voice.call.common.ResultEnum;
import com.voice.call.entity.CallLog;
import com.voice.call.entity.Region;
import com.voice.call.entity.UserAccount;
import com.voice.call.entity.UserInfo;
import com.voice.call.entity.UserLevel;
import com.voice.call.entity.VoiceRate;
import com.voice.call.entity.VosAccount;
import com.voice.call.entity.ChargeLog;
import com.voice.call.exception.CommonException;
import com.voice.call.mapper.RegionMapper;
import com.voice.call.mapper.UserAccountMapper;
import com.voice.call.mapper.UserInfoMapper;
import com.voice.call.mapper.VoiceRateMapper;
import com.voice.call.mapper.ChargeLogMapper;
import com.voice.call.service.ConsumeLogService;
import com.voice.call.service.OpLogService;
import com.voice.call.service.UserAccountService;
import com.voice.call.service.UserInfoService;
import com.voice.call.service.UserLevelService;
import com.voice.call.service.VosService;
import com.voice.call.utils.DateUtil;
import com.voice.call.utils.JSONUtil;

import voice.voice.call.cache.ConfigVosAccountCache;

import com.voice.call.mapper.CallLogMapper;

@Service
public class UserAccountServiceImpl implements UserAccountService{
	
	private static final Logger log = LoggerFactory.getLogger(UserAccountServiceImpl.class);
	
	private static PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();

	@Resource
	private UserAccountMapper userAccountMapper;
	
	@Resource
	private VoiceRateMapper voiceRateMapper;
	
	@Resource
	private UserInfoService userInfoService;
	
	@Resource
	private UserInfoMapper userInfoMapper;
	
	@Resource
	private CallLogMapper callLogMapper;
	
	@Resource
	private ChargeLogMapper chargeLogMapper;
	
	@Resource
	private VosService vosService;
	
	@Resource
	private ConsumeLogService consumeLogService;
	
	@Resource
	private RegionMapper regionMapper;
	
	@Resource
	private UserLevelService userLevelService;
	
	@Resource
	private OpLogService opLogService;
	
	@Resource
	private ConfigVosAccountCache configVosAccountCache;
	
	
	/**
     * 根据国家代码和手机号  判断手机号是否有效
     * @param phoneNumber
     * @param countryCode
     * @return
     */
    private  boolean checkPhoneNumber(String phoneNumber, Integer countryCode){
 
    	try {
    		
		    long phone = Long.parseLong(phoneNumber);
		 
	        PhoneNumber pn = new PhoneNumber();
	        pn.setCountryCode(countryCode);
	        pn.setNationalNumber(phone);
	 
	        return phoneNumberUtil.isValidNumber(pn);
			
		} catch (Exception e) {
			e.printStackTrace();
			log.info("判断手机号码是否有效发生异常");
			return false;
		}
       
 
    }

	
	//帐户拨打
	@Override
	public	Result accountCall(Integer user_id,String called,String lang,String v,String ip){
		
		called = called.replaceAll("[^0-9]+", ""); //被叫号码去悼非法数据
		//资费
		Map<String, Object> qparams = new HashMap<String, Object>();
		qparams.put("callee", called);
		qparams.put("lang", lang);
		VoiceRate ur = voiceRateMapper.getOneLang(qparams);
		if(ur == null){
			//写日志
			opLogService.callWriteLog(user_id, "rate", called+" not found tariff", v, ip);
			log.error("未找到当前拨打国家所需的资费,called={}",called);
			return new Result(ResultEnum.FAILED);
		}
		
		//1.被叫号码处理
		String userCalled = called; //被叫号码
		//被叫号码处理
		if(ur.getRegion()!=null){
			
			userCalled = userCalled.replaceAll("^00"+ur.getRegion().getCode(), "");//去悼前面的区号
			userCalled = userCalled.replaceAll("^[0]{1,}", "");//前悼手机号码前面为0的一个或多个数字
			/**
			if (userCalled.startsWith(ur.getRegion().getCode())) { //判断手机号码是否前面就带有国家码
				userCalled = userCalled.replaceAll("^"+ur.getRegion().getCode(), ""); //去悼国家码
			}
			***/
			//被叫号码处理后，重新取资费
			qparams.put("callee", "00"+ur.getRegion().getCode()+userCalled);
			ur = voiceRateMapper.getOneLang(qparams);
		}
		
		if(ur == null){
			log.error("未找到当前拨打国家所需的资费,called={}",called);
			//写日志
			opLogService.callWriteLog(user_id, "rate", called+" not found tariff", v, ip);
			return new Result(ResultEnum.FAILED);
		}
		
		//2.计算资费
		UserAccount account= userAccountMapper.get(user_id);
		Map<String, Object> rsMap = new HashMap<String, Object>();
		if(account!=null){
			rsMap.put("balance", account.getBalance());
			
			if(account.getBalance().intValue()<0 || account.getBalance().intValue()<ur.getRate().intValue()){
				//写日志
				opLogService.callWriteLog(user_id, "balance", "not enough points", v, ip);
				rsMap.put("leftTime",0);
			}else{
				rsMap.put("leftTime", account.getBalance()/ur.getRate());
			}
			
		}else {
			this.addAccount(user_id);
			rsMap.put("balance", 0);
			rsMap.put("leftTime", 0);
		}
		UserInfo userInfo= userInfoService.getUserForId(user_id);
		
		VosAccount vosAcct = configVosAccountCache.getDefaultVosAccount();
		
		rsMap.putAll(vosService.getVosAccount(vosAcct,String.valueOf(user_id),userInfo.getPhone()));
		rsMap.put("rate", ur.getRate());

		if (ur.getRegion()!=null) {
			rsMap.put("country", ur.getRegion().getName());
			rsMap.put("country_pic", ur.getRegion().getCountryPic());
		}else {
			rsMap.put("country","");
			rsMap.put("country_pic", "");
		}
		
		if(checkPhoneNumber(userCalled,Integer.valueOf(ur.getRegion().getCode()))){ //google 判断手机号码是否有效
			log.info("手机号码判断有效!userCalled={},code={}",userCalled,ur.getRegion().getCode());
			userCalled = "00"+ur.getRegion().getCode()+userCalled;
		}else {
			
			//写日志
			opLogService.callWriteLog(user_id, "called","number error "+userCalled, v, ip);
			log.info("手机号码判断无效");
			userCalled = "";
			
			
		}
		
		if(StringUtils.isEmpty(userCalled)){ //无效手机号码返回错误信息
			rsMap.put("error",ConstLang.getMessage(ResultEnum.INVALID_PHONE_ERROR.toString(), lang));
		}else{
			rsMap.put("error","");
		}
		
		rsMap.put("called",userCalled);
		log.info("拨打请求返回数据为:{}",JSONUtil.mapToJson(rsMap));
		return new Result(rsMap);
	}
	
	//帐户余额
	@Override
	public	Result accountBalance(Integer user_id){
			
		UserAccount account= userAccountMapper.get(user_id);
		Map<String, Object> rsMap = new HashMap<String, Object>();
		if(account!=null){
			rsMap.put("balance", account.getBalance());
		}else {
			this.addAccount(user_id);
			rsMap.put("balance", 0);
		}
		
		int total_integral = consumeLogService.getTodayIntegral(user_id);
		UserLevel level = userLevelService.getUserLevel(total_integral);
		if (level!=null) {
			rsMap.put("level", level.getLevel());
		}else {
			rsMap.put("level", 1);
		}
		
		return new Result(rsMap);
	}
	
	@Override
	public boolean addAccount(Integer user_id){
		
		UserAccount account= userAccountMapper.get(user_id);
		if (account!=null) {
			return true;
		}
		UserAccount entity = new UserAccount();
		entity.setUserId(user_id);
		entity.setBalance(0);
		entity.setGiftMoney(0);
		entity.setStatus(Const.Y);
		entity.setCtime(new Date());
		entity.setMtime(new Date());
		if(userAccountMapper.insert(entity) >0){
			log.error("新增余额帐户成功");
			return true;
		}
		log.error("新增余额帐户失败");
		return false;
	}
	
	//获取帐户
	@Override
	public	UserAccount getUserAccountForUserId(Integer user_id){
		
		UserAccount account= userAccountMapper.get(user_id);
		if (account!=null) {
			return account;
		}
		UserAccount entity = new UserAccount();
		entity.setUserId(user_id);
		entity.setBalance(0);
		entity.setGiftMoney(0);
		entity.setStatus(Const.Y);
		entity.setCtime(new Date());
		entity.setMtime(new Date());
		if(userAccountMapper.insert(entity) >0){
			log.error("新增余额帐户成功");
			return entity;
		}
		log.error("新增余额帐户失败");
		return null;
	}
	
	/**
	 * 获取通话剩余时长(单位秒)
	 * @param caller 主叫
	 * @param called 被叫
	 * @return
	 */
	@Override
	public String getCallLeftTime(String caller,String called){
		
		UserInfo userInfo = userInfoService.findByPhone(caller);
		return this.getLeftTimeForUser(userInfo, called);
	}
	
	@Override
	public String getCallLeftTimeForUserId(String user_id,String called){
		
		UserInfo userInfo =userInfoMapper.get(Integer.valueOf(user_id));
		return this.getLeftTimeForUser(userInfo, called);
	}
	
	private String getLeftTimeForUser(UserInfo userInfo,String called) {
		
		if(userInfo == null){
			log.error("未找到用户");
			return "0";
		}
		UserAccount acct=userAccountMapper.get(userInfo.getId());
		if (acct == null) {
			log.error("未找到帐户余额");
			return "0";
		}
		if (acct.getBalance().equals(0)) {
			log.info("帐户余额为0");
			return "0";
		}
		if (acct.getBalance().intValue() <0) {
			log.info("帐户余额小于0");
			return "0";
		}
		
		
		//资费
		Map<String, Object> qparams = new HashMap<String, Object>();
		qparams.put("callee", called);
		VoiceRate ur = voiceRateMapper.getOne(qparams);
		if(ur == null){
			log.error("未找到当前拨打国家所需的资费,called={}",called);
			return "0";
		}
		
		int leftTime = acct.getBalance()/ur.getRate();
		int totalTime = leftTime * 60;
		log.info("用户id={},可拨打分钟数,leftTime = {},总秒数:{}", userInfo.getId(), leftTime,totalTime);
		return String.valueOf(totalTime);
	}
	
	/***
	 * 扣费处理
	 * @param callLog 话单
	 * @return
	 */
	@Transactional
	@Override
	public boolean DeductionFreeWithCallLog(CallLog entity){
		
		try {
			
			
			//UserInfo user = userInfoService.findByPhone(entity.getCallernum());
			UserInfo user = userInfoService.getUserForId(Integer.valueOf(entity.getCallernum().replaceAll("[^0-9]+", "")));
			if(user != null){
				entity.setCallerUid(user.getId().toString());
			}else{
				
				//写日志
				opLogService.callWriteLog(null, "rateError","not found dial user "+entity.getCallernum()+",length:"+entity.getLength(), null, null);
				
				log.error("未找到扣费用户,phone={}",entity.getCallernum());
				throw new CommonException(ResultEnum.SYSTEM_ERROR);
			}
			
			int d = callLogMapper.insert(entity);
			if (d > 0) {
				log.info("通话记录插入数据库成功!");
			}else{
				
				//写日志
				opLogService.callWriteLog(user.getId(), "callLog","insert log failed,length:"+entity.getLength(), null, null);
				
				log.error("通话记录插入数据库失败!");
				throw new CommonException(ResultEnum.SYSTEM_ERROR);
			}
			
			if(entity.getLength() == 0){
				log.info("拨打时长为0，无需计费!");
				return true;
			}
			
			//获取余额帐户
			UserAccount ua = userAccountMapper.get(user.getId());
			if(ua == null){
				log.error("未找到余额帐户!");
				//写日志
				opLogService.callWriteLog(user.getId(), "callBalance","not account,length:"+entity.getLength(), null, null);
				throw new CommonException(ResultEnum.SYSTEM_ERROR);
			}
			//获取资费
			Map<String, Object> rateParam = new HashMap<String, Object>();
			rateParam.put("callee", entity.getCalled());
			VoiceRate ur = voiceRateMapper.getOne(rateParam);
			if(ur == null){
				log.error("未找到资费!");
				//写日志
				opLogService.callWriteLog(user.getId(), "callRate","not found rate,length:"+entity.getLength(), null, null);
				
				throw new CommonException(ResultEnum.SYSTEM_ERROR);
			}
			
			//获取通话分钟数
			int callLength = entity.getLength();
			if (callLength > 0) {
				if (callLength % 60 == 0) {
					callLength = callLength / 60;
				} else {
					callLength = callLength / 60 + 1;
				}
			}
			
			
			//扣费金额
			int money  = callLength*ur.getRate();
			
			log.info("拨打电话，通话分钟数={},扣费金额={},资费={},扣费前积分={}",callLength,money,ur.getRate(),ua.getBalance());
			
			//更新余额
			UserAccount updateAcc = new UserAccount();
			updateAcc.setBalance(money);
			updateAcc.setUserId(ua.getUserId());
			updateAcc.setMtime(new Date());
			if(userAccountMapper.update(updateAcc)>0){
				log.info("更新余额成功");
				
				//新增扣费记录
				consumeLogService.addConsumeLog(ua.getUserId(), "calls", "calls", money, false, null);
				
				ChargeLog chargeLog = new ChargeLog();
				chargeLog.setCallId(entity.getId());
				chargeLog.setCaller(entity.getCallernum());
				chargeLog.setCallee(entity.getCalled());
				chargeLog.setCallTime(entity.getLength());
				chargeLog.setChargeMoney(money);
				chargeLog.setUserId(ua.getUserId());
				chargeLog.setUnit(60);
				chargeLog.setRate(ur.getRate());
				chargeLog.setStartTime(DateUtil.parse(entity.getStartTime(), DateUtil.DATE_TIME_FMT));
				chargeLog.setStopTime(DateUtil.parse(entity.getStopTime(), DateUtil.DATE_TIME_FMT));
				chargeLog.setCtime(new Date());
				chargeLog.setMtime(new Date());
				//chargeLog.setLang("en");
				chargeLogMapper.insert(chargeLog);//添加扣费记录
				
			}else{
				//写日志
				opLogService.callWriteLog(user.getId(), "userBalance","deduction failed,length:"+entity.getLength(), null, null);
				log.error("更新余额失败");
			}
			
			return true;
			
		} catch (Exception e) {
			e.printStackTrace();
			//写日志
			opLogService.callWriteLog(null, "userBalance","deduction exception,length:"+entity.getLength(), null, null);
			log.error("扣费发生异常");
			return false;
		}
		
	}
	
	/**
	 * 更新帐户余额
	 * @param user_id  更新的帐号
	 * @param money    余额
	 * @param isAdd    true:加钱 false:减钱
	 * @return
	 */
	@Override
	public boolean updateAccountBlance(Integer user_id,Integer money,boolean isAdd){
		UserAccount updateAcc = new UserAccount();
		updateAcc.setBalance(money);
		updateAcc.setUserId(user_id);
		updateAcc.setMtime(new Date());
		if (isAdd) {
		  return userAccountMapper.addBalance(updateAcc)>0?true:false;
		}else {
			return userAccountMapper.update(updateAcc)>0?true:false;
		}
	}
	
	//获取用户可拨打的分钟数
	@Override
	public	String getUserDialMinute(String user_id,String called){
		UserInfo userInfo =userInfoMapper.get(Integer.valueOf(user_id));
		
		if(userInfo == null){
			log.error("未找到用户");
			return "0";
		}
		UserAccount acct=userAccountMapper.get(userInfo.getId());
		if (acct == null) {
			log.error("未找到帐户余额");
			return "0";
		}
		if (acct.getBalance().equals(0)) {
			log.info("帐户余额为0");
			return "0";
		}
		if (acct.getBalance().intValue() <0) {
			log.info("帐户余额小于0");
			return "0";
		}
		
		
		//资费
		Map<String, Object> qparams = new HashMap<String, Object>();
		qparams.put("callee", called);
		VoiceRate ur = voiceRateMapper.getOne(qparams);
		if(ur == null){
			log.error("未找到当前拨打国家所需的资费,called={}",called);
			return "0";
		}
		
		if (acct.getBalance() < ur.getRate()) {
			log.info("帐户余额小于资费");
			return "0";
		}
		
		//int leftTime = acct.getBalance()%ur.getRate() == 0?acct.getBalance()/ur.getRate():(acct.getBalance()/ur.getRate() +1);
		
		int leftTime = acct.getBalance()/ur.getRate();
		//int totalTime = leftTime * 60;
		log.info("用户id={},可拨打分钟数,leftTime = {}", userInfo.getId(), leftTime);
		return String.valueOf(leftTime);
    }
}
